#include "mscatteringlidarform.h"
#include "ui_mscatteringlidarform.h"
#include "../../protocol/gRPC/lidar.pb.h"
#include "../gloab/globalobserver.h"
#include "../gloab/mymessagebox.h"
#include "loopcomputerandgetnextcomputerdata.h"

#include <QMessageBox>
#include <QThread>
#include <QObject>
#include <QMutexLocker>
#include <QTimer>
#include <QDateTime>


MScatteringLidarForm::MScatteringLidarForm(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MScatteringLidarForm)
    , m_client(nullptr)
    //, m_channel(nullptr)
    , m_mutex(new QMutex)
    ,m_loopComputerAndGetComputerData(new LoopComputerAndGetNextComputerData())

{
    QByteArray  byteAry("1234");

    m_guid.set_id(byteAry.data(), byteAry.size());
    ui->setupUi(this);
    connect(this, &MScatteringLidarForm::Sig_sendLidarClient, GlobalObserver::getInstance(), &GlobalObserver::Sig_lidarGetClint);
    formInit();

    connect(this, &MScatteringLidarForm::Sig_startLoopComputerAndGetNextComputerData, m_loopComputerAndGetComputerData,&LoopComputerAndGetNextComputerData::StartThread);
    connect(this, &MScatteringLidarForm::Sig_stopLoopComputerAndGetNextComputerData, m_loopComputerAndGetComputerData,&LoopComputerAndGetNextComputerData::StopThread);
}

MScatteringLidarForm::~MScatteringLidarForm()
{
    delete ui;
}

void MScatteringLidarForm::formInit()
{
    
    //登录按钮，创造channel并初始化存根
    connect(ui->btn_loginLogout, &QPushButton::clicked, this, [=](){
        if(ui->btn_loginLogout->text() == "登录"){
            QString str = ui->edit_ip->text();
            str += ":" + ui->edit_port->text();
            qDebug()<<str.toUtf8().toStdString();

            m_channel = grpc::CreateChannel(str.toUtf8().toStdString(), grpc::InsecureChannelCredentials());
            grpc_connectivity_state channelState = m_channel->GetState(false);
            switch (channelState)
            {
            case GRPC_CHANNEL_IDLE:
                std::cout << "Channel is idle." << std::endl;
                break;
            case GRPC_CHANNEL_CONNECTING:
                std::cout << "Channel is connecting." << std::endl;
                break;
            case GRPC_CHANNEL_READY:
                std::cout << "Channel is ready." << std::endl;
                break;
            case GRPC_CHANNEL_TRANSIENT_FAILURE:
                std::cout << "Channel has transient failure." << std::endl;
                break;
            case GRPC_CHANNEL_SHUTDOWN:
                std::cout << "Channel is shutdown." << std::endl;
                break;
            default:
                std::cout << "Unknown channel state." << std::endl;
                break;
            }
            if(m_channel){
                m_client.reset(new LidarClient(m_channel, this));
                //数据反演时需要调用grpc获取信息，因此将clint暴露给数据反演页面
                emit Sig_sendLidarClient(m_client, m_mutex);
                //连接lidarClient调用完成的信号和自己的槽，使用Qt::QueuedConnection，保证在不同线程能够使用
                //注意必须在clint连接设备成功后才能进行连接信号和槽
                connect(m_client.data(), &LidarClient::Sig_GetPMTState, this, &MScatteringLidarForm::Slot_resGetPMTState, Qt::QueuedConnection);
                connect(m_client.data(), &LidarClient::Sig_StartAcquire, this, &MScatteringLidarForm::Slot_resStartAcquire, Qt::QueuedConnection);
                connect(m_client.data(), &LidarClient::Sig_GetNextComputeData, this, &MScatteringLidarForm::Slot_resGetNextComputeData, Qt::QueuedConnection);
                connect(m_client.data(), &LidarClient::Sig_GetNextData, this, &MScatteringLidarForm::Slot_resGetNextData, Qt::QueuedConnection);
                /*
                    补充登录代码，通过登录代码判断是否登录成功，修改登录的按钮
                */
                ui->btn_loginLogout->setText("退出") ;
                //以下为测试代码
                connect(ui->beginQuerydata, &QPushButton::clicked, this, &MScatteringLidarForm::test_beginQueryData);
                connect(ui->computer, &QPushButton::clicked, this, &MScatteringLidarForm::test_computer);
                connect(ui->getNextComputerData, &QPushButton::clicked, this, &MScatteringLidarForm::test_getNextComputerData);
                connect(ui->setLaser, &QPushButton::clicked, this, &MScatteringLidarForm::test_setLaser);
                connect(ui->getNextData, &QPushButton::clicked, this, &MScatteringLidarForm::test_getNextData);
                connect(ui->moveToAngle, &QPushButton::clicked, this, &MScatteringLidarForm::test_moveToAngle);
            }
        }
        else{
            disconnect(m_client.data(), 0, 0, 0);
            m_client.reset(nullptr);
            m_channel.reset();
            ui->btn_loginLogout->setText("登录");
        }

    });

    //开始采集按钮
    connect(ui->btn_startStopAcquire, &QPushButton::clicked, this, [=](){
        if(!m_client){
            MyMessageBox msgBox(this, MsgBoxType_Info, "雷达未登录");
            msgBox.exec();
            return;
        }
        if(ui->btn_startStopAcquire->text() == "开始采集"){
            ::lidar::AcquireParamsPackage acquireParamsPackage;
            acquireParamsPackage.mutable_id()->CopyFrom(m_guid);
            lidar::OperationParameters* operationParameters = new lidar::OperationParameters;
            
            //采集模式
            operationParameters->set_detectmode(ui->cbx_detectMode->currentIndex());
            //operationParameters->set_detectmode(10);
            //累积时间
            operationParameters->set_duration(ui->cbx_duration->currentText().toDouble());
            //空间分辨率
            operationParameters->set_resolution(ui->cbx_resolution->currentText().toDouble());
            operationParameters->set_frequency(ui->edit_frequence->text().toInt());
            
            acquireParamsPackage.mutable_para()->CopyFrom(*operationParameters);
            QMutexLocker<QMutex> locker(m_mutex.data());
            QSharedPointer<lidar::XError> err = m_client->startAcquire(acquireParamsPackage);
            /*对错误码的解析*/
            //循环获取数据
            m_loopComputerAndGetComputerData->SetClient(m_client);
            m_loopComputerAndGetComputerData->SetDuration(ui->cbx_duration->currentText().toInt());
            m_loopComputerAndGetComputerData->SetGuid(m_guid);
            m_loopComputerAndGetComputerData->SetMutex(m_mutex);
            //m_loopComputerAndGetComputerData->StartThread();
            emit Sig_startLoopComputerAndGetNextComputerData();
            qDebug()<<"ui->cbx_duration->currentText().toInt()"<<ui->cbx_duration->currentText().toInt();

            ui->btn_startStopAcquire->setText("停止采集");
        }
        else{

            {
            QMutexLocker<QMutex> locker(m_mutex.data());
            m_client->stopAcquire(m_guid);
            }
            // 请求线程结束
            emit Sig_stopLoopComputerAndGetNextComputerData();
            //m_loopComputerAndGetComputerData->StopThread();
            ui->btn_startStopAcquire->setText("开始采集");
        }
    });
}

void MScatteringLidarForm::test_computer()
{
    lidar::ComputeParamsPackage computeParamsPackage;
    QDateTime currentDateTime = QDateTime::currentDateTime().addSecs(-300);
    google::protobuf::Timestamp startTime, endTime;

    qint64 seconds = currentDateTime.toSecsSinceEpoch();
    qint64 msecs = currentDateTime.toMSecsSinceEpoch() % 1000;
    startTime.set_seconds(seconds);
    startTime.set_nanos(msecs * 1000000);
    qDebug()<<" startTime.seconds:"<<seconds<<" startTime.nanos:"<<msecs * 1000000;

    currentDateTime = QDateTime::currentDateTime();
    seconds = currentDateTime.toSecsSinceEpoch();
    msecs = currentDateTime.toMSecsSinceEpoch() % 1000;
    endTime.set_seconds(seconds);
    endTime.set_nanos(msecs * 1000000);
    qDebug()<<" endTime.seconds:"<<seconds<<" endTime.nanos:"<<msecs * 1000000;

    lidar::AlgrithmParams algrithmParams;

    computeParamsPackage.mutable_methodparams()->CopyFrom(algrithmParams);
    computeParamsPackage.mutable_dtfrom()->CopyFrom(startTime);
    computeParamsPackage.mutable_dtto()->CopyFrom(endTime);
    computeParamsPackage.mutable_id()->CopyFrom(m_guid);

    QMutexLocker<QMutex> locker(m_mutex.data());
    m_client->compute(computeParamsPackage);

}

void MScatteringLidarForm::test_getNextComputerData()
{
    lidar::AlgrithmParamsPackage algrithmParamsPackage;
    algrithmParamsPackage.mutable_id()->CopyFrom(m_guid);
    algrithmParamsPackage.set_requestedmethods(0x0400);

    QSharedPointer<lidar::ComputedResult> response = m_client->getNextComputerData(algrithmParamsPackage);
    int metheadSize = response->methods_size();
    int extinctionCoefficientIndex = 0;
    for(int i = 0; i < metheadSize; i++){
        if(response->methods(i) == 0x0400){
            extinctionCoefficientIndex = i;
        }
    }
    
    const std::string& temp = response->data(extinctionCoefficientIndex);
    qDebug()<<"解压前数据长度"<<temp.size();
    QByteArray compressDataElement = QByteArray::fromRawData(temp.data(), temp.size());
    QByteArray unCompressDataElement = qUncompress(compressDataElement);

    QVector<float>  extinctionCoefficientVec;
    const float* floatPtr = reinterpret_cast<const float*>(unCompressDataElement.data());
    for(int i = 0; i < unCompressDataElement.size() / sizeof(float); i++){
        extinctionCoefficientVec.push_back(floatPtr[i]);
    }

    qDebug() << " size:" << extinctionCoefficientVec.size();
    for(int i = 0; i < 10; i++){
        qDebug() << " data:" << extinctionCoefficientVec[i];    
    }

}

void MScatteringLidarForm::test_setLaser()
{
    lidar::LaserLD laserLD;
    laserLD.mutable_id()->CopyFrom(m_guid);
    int strength = 0;
    if(ui->cbx_setLaser->currentIndex() == 0){
        strength = 650;
    }else if(ui->cbx_setLaser->currentIndex() == 1){
        strength = 700;
    }else{
        strength = 800;
    }
    laserLD.set_syscurrent(strength);
    laserLD.set_en(true);
    m_client->setLaser(laserLD);
}

void MScatteringLidarForm::test_beginQueryData()
{
    lidar::RawParamsPackage rawParamsPackage;
    rawParamsPackage.mutable_id()->CopyFrom(m_guid);
    QDateTime currentDateTime = QDateTime::currentDateTime().addMonths(-5);
    google::protobuf::Timestamp startTime, endTime;

    qint64 seconds = currentDateTime.toSecsSinceEpoch();
    qint64 msecs = currentDateTime.toMSecsSinceEpoch() % 1000;
    startTime.set_seconds(seconds);
    startTime.set_nanos(msecs * 1000000);

    currentDateTime = QDateTime::currentDateTime();
    seconds = currentDateTime.toSecsSinceEpoch();
    msecs = currentDateTime.toMSecsSinceEpoch() % 1000;
    endTime.set_seconds(seconds);
    endTime.set_nanos(msecs * 1000000);

    rawParamsPackage.mutable_dtfrom()->CopyFrom(startTime);
    rawParamsPackage.mutable_dtto()->CopyFrom(endTime);

    m_client->beginQueryData(rawParamsPackage);

}

void MScatteringLidarForm::test_getNextData()
{
    QSharedPointer<lidar::LidarRawData> lidarRawData = m_client->getNextData(m_guid);
    const std::string& temp = lidarRawData->bbin();
    QByteArray compressDataElement = QByteArray::fromRawData(temp.data(), temp.size());
    QByteArray unCompressDataElement = qUncompress(compressDataElement);
    QVector<float>  extinctionCoefficientVec;
    const float* floatPtr = reinterpret_cast<const float*>(unCompressDataElement.data());
    for(int i = 0; i < unCompressDataElement.size() / sizeof(float); i++){
        extinctionCoefficientVec.push_back(floatPtr[i]);
    }

    qDebug() << " size:" << extinctionCoefficientVec.size();
    for(int i = 0; i < 10; i++){
        qDebug() << " bbin ith data :" << extinctionCoefficientVec[i];
    }
    qDebug()<<lidarRawData->acquiredat().seconds();

    qDebug()<<"温度: "<<lidarRawData->temperature()<<"湿度: "<<lidarRawData->humidity()<<"压力: "<<lidarRawData->atompressure();
}

void MScatteringLidarForm::test_moveToAngle()
{
    lidar::RocMovePara rocMovePara;
    rocMovePara.mutable_id()->CopyFrom(m_guid);
    rocMovePara.set_dir(true);
    rocMovePara.set_angle(ui->edit_movetoAngle->text().toInt());

    m_client->setRocMoveToAngle(rocMovePara);
}

// 未完成
void MScatteringLidarForm::test_allwork()
{
    /*登录*/
    
    //开光
    // int strength = 700;
    // lidar::LaserLD laserLD;
    // laserLD.mutable_id()->CopyFrom(m_guid);
    // laserLD.set_syscurrent(strength);
    // laserLD.set_en(true);
    // m_client->setLaser(laserLD);
    // //开始采集
    // ::lidar::AcquireParamsPackage acquireParamsPackage;
    // acquireParamsPackage.mutable_id()->CopyFrom(m_guid);
    // lidar::OperationParameters* operationParameters = new lidar::OperationParameters;
    // //operationParameters
    // operationParameters->set_detectmode(ui->cbx_detectMode->currentIndex());
    // operationParameters->set_duration(ui->cbx_duration->currentText().toInt());
    // operationParameters->set_resolution(ui->cbx_resolution->currentText().toInt());

    // acquireParamsPackage.mutable_para()->CopyFrom(*operationParameters);
    // QMutexLocker<QMutex> locker(m_mutex.data());
    // QSharedPointer<lidar::XError> err = m_client->startAcquire(acquireParamsPackage);
    // //循环获取数据
    // QThread *therad = new QThread;



}

void MScatteringLidarForm::Slot_resGetPMTState(const QSharedPointer<lidar::RuntimeParamsPackage> response)
{


}

void MScatteringLidarForm::Slot_resStartAcquire(const QSharedPointer<lidar::XError>)
{

}

void MScatteringLidarForm::Slot_resGetNextComputeData(const QSharedPointer<lidar::ComputedResult>)
{

}

void MScatteringLidarForm::Slot_resGetNextData(const QSharedPointer<lidar::LidarRawData>)
{

}

//循环computer  和 getNextComputerData
// void LoopComputerAndGetComputerData::run()
// {
//     qDebug()<<"进入线程 线程id" << QThread::currentThread()<<"m_duration = "<<m_duration;
//     QThread::sleep(3*m_duration/2);
//     //getNextComputerData,需要记录一个最后采集lastTime，如果获取到的时间小于lastTime，则跳过，直到获取到大于lastTime的时间
//     google::protobuf::Timestamp lastTime;
//     lastTime.set_seconds(1000); //lastTime随便设个非0的值，在getNextComputerData之后就会更新此数
//     while(1){
//         //computer
//         lidar::ComputeParamsPackage computeParamsPackage;
//         QDateTime currentDateTime = QDateTime::currentDateTime().addSecs(-m_duration);
//         google::protobuf::Timestamp startTime, endTime;
//         qint64 seconds = currentDateTime.toSecsSinceEpoch();
//         qint64 msecs = currentDateTime.toMSecsSinceEpoch() % 1000;
//         startTime.set_seconds(seconds);
//         startTime.set_nanos(msecs * 1000000);

//         currentDateTime = QDateTime::currentDateTime();
//         seconds = currentDateTime.toSecsSinceEpoch();
//         msecs = currentDateTime.toMSecsSinceEpoch() % 1000;
//         endTime.set_seconds(seconds);
//         endTime.set_nanos(msecs * 1000000);

//          lidar::AlgrithmParams algrithmParams;

//         computeParamsPackage.mutable_methodparams()->CopyFrom(algrithmParams);
//         computeParamsPackage.mutable_dtfrom()->CopyFrom(startTime);
//         computeParamsPackage.mutable_dtto()->CopyFrom(endTime);
//         computeParamsPackage.mutable_id()->CopyFrom(m_guid);
//         {
//             qDebug()<<"-------------------------computer--------------------------";
//             QMutexLocker<QMutex> locker(m_mutex.data());
//             m_client->compute(computeParamsPackage);
//         }

//         while(true){
//             lidar::AlgrithmParamsPackage algrithmParamsPackage;
//             algrithmParamsPackage.mutable_id()->CopyFrom(m_guid);
//             algrithmParamsPackage.set_requestedmethods(0x0400);
//             QSharedPointer<lidar::ComputedResult> response;
//             {
//                 qDebug()<<"-------------------------getNextComputerData--------------------------";
//                 QMutexLocker<QMutex> locker(m_mutex.data());
//                 response = m_client->getNextComputerData(algrithmParamsPackage);
//             }
//             if(!response){
//                 break;
//             }else{
//                 lastTime = response->acquiredat();

//                 if(lastTime.seconds() == 0 && lastTime.nanos() == 0 ){
//                     qDebug()<<"acquiredat 为空";
//                     break;
//                 }
//             }


//             //获取消光系数的数据所在位置
//             int metheadSize = response->methods_size();
//             int extinctionCoefficientIndex = 0;
//             for(int i = 0; i < metheadSize; i++){
//                 if(response->methods(i) == 0x0400){
//                     extinctionCoefficientIndex = i;
//                 }
//             }
            
//             const std::string& temp = response->data(extinctionCoefficientIndex);
//             QByteArray compressDataElement = QByteArray::fromRawData(temp.data(), temp.size());
//             QByteArray unCompressDataElement = qUncompress(compressDataElement);

//             QVector<float>  extinctionCoefficientVec;
//             const float* floatPtr = reinterpret_cast<const float*>(unCompressDataElement.data());
//             for(int i = 0; i < unCompressDataElement.size() / sizeof(float); i++){
//                 extinctionCoefficientVec.push_back(floatPtr[i]);
//             }

//             qDebug() << " size:" << extinctionCoefficientVec.size();
//             for(int i = 0; i < 10; i++){
//                 qDebug() << " data:" << extinctionCoefficientVec[i];
//             }
//         }
//         //
//         QThread::sleep(m_duration);
//     }
//     qDebug()<<"结束线程 线程id" << QThread::currentThread();
// }
